package com.jron.cqiu.kernel.implement.crossos.jna;

import com.sun.jna.examples.win32.*;
import com.sun.jna.examples.win32.User32.MSG;
import com.sun.jna.examples.win32.User32.LowLevelKeyboardProc;
import com.sun.jna.examples.win32.User32.KBDLLHOOKSTRUCT;
import com.sun.jna.examples.win32.W32API.LRESULT;
import com.sun.jna.examples.win32.W32API.WPARAM;
import com.sun.jna.examples.win32.W32API.HMODULE;
import com.sun.jna.examples.win32.User32.HHOOK;
import com.sun.jna.examples.KeyboardUtils;
import com.jron.cqiu.kernel.handlers.IHotKeyRegister;
import com.jron.cqiu.kernel.execution.IExecution;

import java.awt.event.KeyEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Created by Intellij IDEA.
 *
 * @Author: Yejw
 * @Date: 2008-6-26
 * @Time: 13:37:17
 */
public class HotKeyRegister implements IHotKeyRegister {

    private static Log log = LogFactory.getLog(HotKeyRegister.class);

    private static volatile boolean quit;
    private static HHOOK hhk;
    private static LowLevelKeyboardProc keyboardHook;

    public void registerHotkey() {
        final User32 lib = User32.INSTANCE;
        HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);

        keyboardHook = new LowLevelKeyboardProc() {
            public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
                boolean csa = KeyboardUtils.isPressed(KeyEvent.VK_CONTROL)
                        && KeyboardUtils.isPressed(KeyEvent.VK_SHIFT)
                        && KeyboardUtils.isPressed(KeyEvent.VK_ALT);
                int vkc = info.vkCode;

                if (nCode >= 0) {
                    switch (wParam.intValue()) {
                        case User32.WM_KEYUP:
                        case User32.WM_KEYDOWN:
                        case User32.WM_SYSKEYUP:
                        case User32.WM_SYSKEYDOWN:

                            //ctrl+shift+alt+s   shutdown scheduler waitForJobsToComplete
                            if (csa && vkc == KeyEvent.VK_S)
                                IExecution.INSTANCE.shutdownScheduler(true);

                            //ctrl+shift+alt+e   shutdown scheduler  immediately
                            if (csa && vkc == KeyEvent.VK_E)
                                IExecution.INSTANCE.shutdownScheduler(false);

                            //ctrl+shift+alt+p  exit king system waitForJobsToComplete
                            if (csa && vkc == KeyEvent.VK_P) {
                                IExecution.INSTANCE.shutdownScheduler(true);
                                quit = true;
                            }
                            //ctrl+shift+alt+o exit king system immediately
                            if (csa && vkc == KeyEvent.VK_O) {
                                IExecution.INSTANCE.shutdownScheduler(false);
                                quit = true;
                            }
                    }
                }
                return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
            }
        };
        hhk = lib.SetWindowsHookEx(User32.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
        log.debug("\n Successfully to register hot keys! King system has been started!\n");

        new Thread() {
            public void run() {
                while (!quit) {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                lib.UnhookWindowsHookEx(hhk);
                log.info("\nUnhook and exit.King System has been shutted down!\n");
                System.exit(0);
            }
        }.start();

        // This bit never returns from GetMessage
        int result;
        MSG msg = new MSG();
        while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
            if (result == -1) {
                System.err.println("error in get message");
                break;
            } else {
                System.err.println("got message");
                lib.TranslateMessage(msg);
                lib.DispatchMessage(msg);
            }
        }
        lib.UnhookWindowsHookEx(hhk);
    }
}